package com.enbatis.mybatisplugs.generate;

import com.enbatis.mybatisplugs.commons.utils.LineHumpUtil;
import com.enbatis.mybatisplugs.generate.utils.FreeMarkerTemplateUtils;
import freemarker.template.Template;

import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.*;

public class CodeGenerator2 {



    private  String AUTHOR;

    private final String CURRENT_DATE = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());

    private  String tableName;

    private  String packageName;

    private final String tableAnnotation = "";

    private  String URL ;

    private  String USER;

    private  String PASSWORD ;

    private final String DRIVER = "com.mysql.cj.jdbc.Driver";

    private  String diskPath ;

    private  String changeTableName ;

    public Connection getConnection() throws Exception{
        Class.forName(DRIVER);
        Connection connection= DriverManager.getConnection(URL, USER, PASSWORD);
        return connection;
    }

    public CodeGenerator2(String  url,String user,String password, String diskPath){
        this.URL=url;
        this.USER=user;
        this.PASSWORD=password;
        this.diskPath=diskPath;
    }


    public  void generate(Class clazz) {
       this.packageName= clazz .getPackage().getName();
        Scanner scanAutho = new Scanner(System.in);
        // 从键盘接收数据

        // next方式接收字符串
        System.out.println("请输入作者：");
        // 判断是否还有输入
        if (scanAutho.hasNext()) {
            String author = scanAutho.next();
            this.AUTHOR=author;
        }




        Scanner scanTable = new Scanner(System.in);
        // 从键盘接收数据

        // next方式接收字符串
        System.out.println("请输入表名：");
        // 判断是否还有输入
        if (scanTable.hasNext()) {
            String tableName = scanTable.next();
            this.tableName=tableName;
        }
        scanAutho.close();
        scanAutho.close();

        try {


            this.changeTableName= LineHumpUtil.lineToBigHump(this.tableName);
            Connection connection = getConnection();
            DatabaseMetaData databaseMetaData = connection.getMetaData();
            ResultSet resultSet = databaseMetaData.getTables(null,"%", tableName,null);
            //生成Mapper文件

            List<TableInfo> tableInfoList=getTableList(resultSet);

            generateMapperFile(resultSet);
            //生成entity实体类
            generateJavaFile(tableInfoList,"entity.ftl",".java");
            //生成service类
            generateJavaFile(tableInfoList,"service.ftl","Service.java");
            //生成serviceImpl类
            generateJavaFile(tableInfoList,"serviceImpl.ftl","ServiceImpl.java");

            //生成controller类
            generateJavaFile(tableInfoList,"controller.ftl","Controller.java");
            //生成mapping文件
            generateJavaFile(tableInfoList,"mapping.ftl","Mapper.xml");

        } catch (Exception e) {
            throw new RuntimeException(e);
        }finally{

        }
    }



   public List<TableInfo> getTableList(ResultSet resultSet){

       List<TableInfo> list=new ArrayList<>();
       try{
           while (resultSet.next()){
               String tableName=resultSet.getString("TABLE_NAME");
               System.out.println(tableName);

               String remark = resultSet.getString("REMARKS");
               TableInfo tableInfo=new TableInfo();
               tableInfo.setTableName(tableName);
               tableInfo.setTableRemark(remark);
               List<Column> columnList=new ArrayList<>();
               Connection connection = getConnection();
               DatabaseMetaData databaseMetaData = connection.getMetaData();

               ResultSet rs = databaseMetaData.getColumns(null,"%", tableName,"%");
               while (rs.next()){
                   String colName = rs.getString("COLUMN_NAME");

                   String remarks = rs.getString("REMARKS");

                   String dbType = rs.getString("TYPE_NAME");
                   System.out.println("---"+colName+"---"+remarks+"---"+dbType);
                   Column column=new Column();
                   column.setColumnName(colName);
                   column.setColumnComment(remarks);
                   column.setColumnType(changeDbType(dbType));
                   columnList.add(column);

               }
               tableInfo.setColumnList(columnList);
               list.add(tableInfo);
           }

       }catch (Exception e){
             e.printStackTrace();
       }
           return  list;
    }


    private void generateMapperFile(ResultSet resultSet) throws Exception{

        final String suffix = "Mapper.java";
        final String path = diskPath + changeTableName + suffix;
        final String templateName = "mapper.ftl";
        File file = new File(diskPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        File mapperFile = new File(path);
        Map<String,Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName,mapperFile,dataMap);

    }


    private void generateJavaFile( List<TableInfo> tableInfoList,String templateName,String suffix ) throws Exception{

        for (TableInfo tableInfo:tableInfoList) {
            final String path = diskPath + tableInfo.getBigEntityName() + suffix;
            File file = new File(diskPath);
            if (!file.exists()) {
                file.mkdirs();
            }
            File entityFile = new File(path);
            Map<String,Object> dataMap = new HashMap<>();
            Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
            FileOutputStream fos = new FileOutputStream(entityFile);
            dataMap.put("table_name_small",tableInfo.getTableName());
            dataMap.put("small_hump_table_name",tableInfo.getSmallEntityName());
            dataMap.put("table_name",tableInfo.getBigEntityName());
            dataMap.put("author",AUTHOR);
            dataMap.put("date",CURRENT_DATE);
            dataMap.put("package_name", this.packageName);
            dataMap.put("table_annotation",tableInfo.getTableRemark());
            dataMap.put("columnList",tableInfo.getColumnList());
            Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"),10240);
            template.process(dataMap,out);
        }




    }




    private void generateFileByTemplate(final String templateName,File file,Map<String,Object> dataMap) throws Exception{
        Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
        FileOutputStream fos = new FileOutputStream(file);
        dataMap.put("table_name_small",tableName);
        dataMap.put("table_name",changeTableName);
        dataMap.put("author",AUTHOR);
        dataMap.put("date",CURRENT_DATE);
        dataMap.put("package_name", this.packageName);
        dataMap.put("table_annotation",tableAnnotation);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"),10240);
        template.process(dataMap,out);
    }


    private static String changeDbType(String dbType) {
        dbType = dbType.toUpperCase();
        switch(dbType){
            case "VARCHAR":
            case "VARCHAR2":
            case "LONGTEXT":
            case "CHAR":
                return "String";
            case "NUMBER":
            case "DECIMAL":
                return "BigDecimal";
            case "INT":
            case "SMALLINT":
            case "INTEGER":
                return "Integer";
            case "BIGINT":
                return "Long";
            case "DATETIME":
            case "TIMESTAMP":
            case "DATE":
                return "Date";
            default:
                return "1";
        }
    }





}
